#ifndef __GLOBAL__
#define __GLOBAL__

//#undef NDEBUG
//#define DEBUG

#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN // resolve glog compatibility with window.h
//#define _SECURE_SCL 1 // disables Microsoft's "safe" extensions.
#define _CRT_SECURE_NO_WARNINGS // disable unsafe deprecation
#define _SCL_SECURE_NO_WARNINGS
#endif
#include "stdio64.h"
#include <glog/logging.h>
#include <limits>
#include <cstdlib>
#include <cstring>
// Defines logging level, uncomment to disable info level logging
//#define GOOGLE_STRIP_LOG 1
// It is better to use parameter or environment variables
// We can set it in debug option or shell.
// If minloglevel > 0, verbose will not be effective

using namespace std;

/* Windows */
#if _WIN32
/* long long on WIN32 is 64 bits */
#define GINT64 long long 
#define GUINT64 unsigned long long

/* snprintf is _snprintf on windows */
#define snprintf _snprintf

/* the location of the header defining hash functions */
#define HASH_FUN_H  <hash_map>

/* the namespace of the hash<> function */
#define HASH_NAMESPACE  stdext

/* The system-provided hash function including the namespace. */
#define SPARSEHASH_HASH  HASH_NAMESPACE::hash_compare

/* The system-provided hash function, in namespace HASH_NAMESPACE. */
#define SPARSEHASH_HASH_NO_NAMESPACE  hash_compare

/* Linux or Cygwin */
#else
/* 32-bit Linux has long 32-bit */
#if __i386
#define GINT64 long long
#define GUINT64 unsigned long long

/* Cygwin has same type as WIN32 */
#elif __CYGWIN__
#define GINT64 long long 
#define GUINT64 unsigned long long

/* long on 64-bit Linux is 64 bits */
#else
#define GINT64 long
#define GUINT64 unsigned long
#endif

/* the location of the header defining hash functions */
#define HASH_FUN_H  <tr1/functional>

/* the namespace of the hash<> function */
#define HASH_NAMESPACE  std::tr1

/* The system-provided hash function including the namespace. */
#define SPARSEHASH_HASH  HASH_NAMESPACE::hash

/* The system-provided hash function, in namespace HASH_NAMESPACE. */
#define SPARSEHASH_HASH_NO_NAMESPACE  hash
#endif

/* The google sparse_hash_map header location. */
#define SPARSEHASHMAP_H  <google/sparse_hash_map>
#define SPARSEHASHSET_H  <google/sparse_hash_set>
#define DENSEHASHMAP_H  <google/dense_hash_map>

/* Type defination */
#define GBYTE unsigned char
#define GUINT32 unsigned int
#define GINT32 int

typedef GINT32 GID_T;
typedef GID_T  GCOUNT_T;

#define GENE_A 0
#define GENE_G 1
#define GENE_C 2
#define GENE_T 3
//#define CompressedKmer GINT64
#define MAXREADLENGTH 1024
#define QUARTER_MAX_KMER_LEN 16
#define MAXKMERLENGTH 63 //QUARTER_MAX_KMER_LEN = (MAXKERLENGTH  + 3) / 4
#define MAXCONTIGLENGTH 100000000
static const double DOUBLE_MAX = std::numeric_limits<double>::max();
static const char DICT[4] = {'A', 'G', 'C', 'T'};
static char shared_buffer[10000000];
/**
 * 	Encodes base to two bits.
 *
 * @author	Tao Yu
 * @date	2011/3/23
 *
 * @param	ch	The base char A/T/C/G.
 *
 * @return	The encoded base bits are last two bits.
 */
inline unsigned char encode(char ch)
{
	switch(ch) {
	case 'A': return GENE_A;
	case 'G': return GENE_G;
	case 'C': return GENE_C;
	case 'T': return GENE_T;
	default: LOG(FATAL) << "undefined char " << ch;
	}
}

/**
 * 	Decodes the code's last two bits to char.
 *
 * @author	Tao Yu
 * @date	2011/3/23
 *
 * @param	i	The code.
 *
 * @return	The base char A/T/C/G.
 */
inline char decode(unsigned char i)
{
	switch(i) {
	case GENE_A: return 'A';
	case GENE_G: return 'G';
	case GENE_C: return 'C';
	case GENE_T: return 'T';
	default: LOG(FATAL) << "undefined code " << i;
	}
}

/**
 * 	Get the reverse complement of the source base sequence.
 *
 * @author	Tao Yu
 * @date	2011/3/23
 *
 * @param [in]	source	Source kmer sequence buffer.
 * @param [out]	dest  	Destination kmer sequence buffer.
 *
 * @return	null if it fails, else.
 */
char* reverseComplement(char* source, char* dest);

#endif
